using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class LoadAssetTask : BaseTask
{
    private AsyncOperationHandle _handle;

    private LoadAssetCallBack _loadAssetCallBack;

    private string _uniqueKey;

    private object _userData;

    private TaskStatus _status;

    public TaskStatus Status => _status;

    public override float Percent
    {
        get
        {
            if (_status == TaskStatus.UnStart)
                return 0;

            if (_status == TaskStatus.Fail)
                return 0;

            if (_status == TaskStatus.Suc)
                return 1;

            return GetPercent();
        }
    }

    public override bool IsDone => _handle.IsDone;

    public void Start<T>()
    {
        _handle = Addressables.LoadAssetAsync<T>(_uniqueKey);
        _status = TaskStatus.Doing;
    }

    public override void Update(float deltaTime, float realDeltaTime)
    {
        //正在进行
        if (_status != TaskStatus.Doing)
            return;

        //加载完成
        if (_status == TaskStatus.Suc)
            return;

        if (_status == TaskStatus.Fail)
            return;

        if (!_handle.IsDone)
        {
            OnLoadUpdate();
            return;
        }

        if (_handle.IsDone)
        {
            OnLoadComplete();
        }
    }

    public LoadAssetTask(string uniqueKey, LoadAssetCallBack loadAssetCallBack)
    {
        _uniqueKey = uniqueKey;
        _loadAssetCallBack = loadAssetCallBack;
        _status = TaskStatus.UnStart;
    }

    public LoadAssetTask(string uniqueKey,LoadAssetCallBack loadAssetCallBack,object userData)
    {
        _uniqueKey = uniqueKey;
        _loadAssetCallBack = loadAssetCallBack;
        _status = TaskStatus.UnStart;
        _userData = userData;
    }

    private void OnLoadComplete()
    {
        var resultStatus = _handle.Status;
        switch (resultStatus)
        {
            case AsyncOperationStatus.Succeeded:
                OnLoadSuc();
                break;
            case AsyncOperationStatus.Failed:
                OnLoadFail();
                break;
        }
    }

    private void OnLoadSuc()
    {
        _status = TaskStatus.Suc;
        var sucCallBack = _loadAssetCallBack.LoadAssetSucCallBack;
        var result = _handle.Result;
        sucCallBack?.Invoke(_uniqueKey, result, _userData);
    }

    private void OnLoadFail()
    {
        _status = TaskStatus.Fail;
        var failCallBack = _loadAssetCallBack.LoadAssetFailCallBack;
        failCallBack?.Invoke(_uniqueKey, string.Empty,_userData);
    }

    private void OnLoadUpdate()
    {
        var updateCallBack = _loadAssetCallBack.LoadAssetUpdateCallBack;
        var loadStatus = _handle.GetDownloadStatus();
        updateCallBack?.Invoke(_uniqueKey, loadStatus.DownloadedBytes, loadStatus.TotalBytes, loadStatus.Percent);
    }

    private float GetPercent()
    {
        if(_status == TaskStatus.UnStart)
            return 0;

        if(_status == TaskStatus.Fail)
            return 0;

        if(_status == TaskStatus.Suc)
            return 1;

        var loadStatus = _handle.GetDownloadStatus();
        return loadStatus.Percent;
    }

    public override void Release()
    {
        _status = TaskStatus.UnStart;
        _loadAssetCallBack = null;
        _uniqueKey = string.Empty;
        Addressables.Release(_handle);
    }
}
